<?php
/**
 * Class UserLogic
 * @package app\common\logic
 */

namespace app\common\logic;
use think\Log;

/**
 * 图片相关逻辑
 *
 * @package app\common\logic
 */
class Img extends Base
{

    //允许的图片类型
    private $imgType = [
        IMG_TYPE_ASSET,
        IMG_TYPE_ASSET_PARTS,
        IMG_TYPE_AFTER_SALE_APPLY,
        IMG_TYPE_AFTER_SALE_SOLVED,
        IMG_TYPE_ASSET_INSTALL,
        IMG_TYPE_ASSET_SHIP,
    ];

    private $request;

    private $imgModel;

    //图片上传的顶级目录
    private $imgUploadPath = IMG_PATH;

    //单个类型的图片总数限制
    private $imgLimitCounts = 20;

    //单个图片的大小限制（字节）
    private $imgEachLimitSize = 2*1024*1024;


    public function __construct($data = [])
    {
        parent::__construct($data);
        $this->imgModel = model('Imgs');
        $this->request = request();
    }

    /**
     * 图片上传
     *
     * @author mayy
     * @date 2017-8-15
     * @param $table_name
     * @param $data_id
     * @param $img_type
     * @return boolean
     */
    public function uploadImg($table_name, $data_id, $img_type)
    {

        // 获取表单上传文件
        if (empty($files = $this->request->file('file'))) {
            //没有图片上传
            Log::record('---没有图片上传---');
            return true;
        }

        $upload_img_log = json_encode($files, JSON_UNESCAPED_UNICODE);
        Log::record("---开始上传图片(数量：{$upload_img_log})---");

        //TODO 上传秘钥验证

        if (empty($table_name) || $data_id <= 0) {
            exception('上传图片缺少必要的参数！');
        }

        if (!in_array($img_type, $this->imgType)) {
            exception('图片类型参数错误！');
        }

        //数量验证
        $check_count = $this->checkImgCounts($table_name, $data_id, count($files));
        if (!$check_count) {
            exception('图片数量超出限制！');
        }

        //大小验证
        foreach($files as $file){
            $file_info = $file->getInfo();
            if ($file_info['size'] > $this->imgEachLimitSize) {
                Log::record('上传的图片文件超出限制：' . $file_info['size']);
                exception('图片大小超出限制！');
            }
        }

        $flag = true;
        $img_url_saved = [];    //上传成功的照片物理地址

        foreach($files as $file){
            //图片存放规则： /mnt/www/File/项目名称/Img/图片类型/年月日/图片文件
            //存入数据库的部分为： 图片类型/年月日/图片文件

            $sava_path = $this->getImgUploadDir($img_type);
            if ($sava_path == false) {
                exception('图片上传路径生成失败，请联系工程师处理！');
            }

            //如果有同名文件，不覆盖
            $info = $file->rule('uniqid')->move($sava_path, true, false);
            if($info){
                //文件上传成功,写入数据库
                $img_url = ltrim(str_replace($this->imgUploadPath, '', $sava_path), '/') . $info->getSaveName();

                $img_data = [
                    'img_type' => $img_type,
                    'table_name' => $table_name,
                    'table_id' => $data_id,
                    'img_url' => $img_url,  //存数据库只存 IMG_PATH后面的部分
                ];
                $data_res = $this->imgModel->addImg($img_data);
                if ($data_res == false) {
                    //保存图片路径信息失败
                    Log::record('保存图片路径信息失败：' . $this->imgModel->getLastSql());
                    $this->errorInfo = '保存图片路径信息失败！';
                    $flag = false;
                    break;
                }

                $img_url_saved[] = $sava_path;
            }else{
                // 上传失败获取错误信息
                Log::record('图片上传失败，错误原因：' . $file->getError());
                $this->errorInfo = '图片文件保存失败！';
                $flag = false;
                break;
            }
        }

        if (!$flag && !empty($img_url_saved)) {
            $this->delImgFromDisk($img_url_saved);
        }

        $res = $flag ? '成功' : '失败';
        Log::record("---图片上传完毕，结果：{$res}---");

        return $flag;
    }

    /**
     * 删除磁盘上面的文件
     *
     * @author mayy
     * @date 2017-8-17
     * @param $img_url_saved
     * @param boolean $full_path 是否是完整的路径
     * @return bool
     */
    private function delImgFromDisk($img_url_saved, $full_path = true)
    {
        if (!is_array($img_url_saved)) {
            $img_url_saved = [$img_url_saved];
        }

        foreach ($img_url_saved as $v) {
            if (!$full_path) {
                $path = $this->imgUploadPath . $v;
            } else {
                $path = $v;
            }
            if (file_exists($path)) {
                @unlink($path);
            }
        }

        return true;
    }

    /**
     * 生成图片上传路径
     *
     * @param $img_type
     * @return string
     */
    private function getImgUploadDir($img_type)
    {
        $dir = $this->imgUploadPath . DIRECTORY_SEPARATOR . $img_type . DIRECTORY_SEPARATOR . date('ymd') . DIRECTORY_SEPARATOR;
        if (!file_exists($dir)) {
            $res = @mkdir($dir, 0755, true);
            if (!$res) {
                Log::record('路径创建失败：' . $dir);
                return false;
            }
        }
        return $dir;
    }


    /**
     * 检查图片上传数量是否超出限制.
     *
     * @author mayy
     * @date 2017-8-15
     * @param $table_name
     * @param $data_id
     * @param $upload_counts
     * @return bool
     */
    private function checkImgCounts($table_name, $data_id, $upload_counts)
    {
        $where = [
            'table_name' => $table_name,
            'table_id'   => $data_id,
        ];
        $uploaded = $this->imgModel->getList($where, 1, true);
        if (($upload_counts + $uploaded) > $this->imgLimitCounts) {
            Log::record('图片数量超出限制，已上传数量：' . $uploaded . '本次上传数量：' . $upload_counts);
            return false;
        }
        return true;
    }
    /**
     * 根据图片主键id删除图片,一个或者多个
     *
     * @author mayy
     * @date 2017-8-15
     * @param array $img_ids
     * @return bool
     */
    public function deleteImgById(array $img_ids)
    {
        if (empty($img_ids)) {
            return false;
        }

        $where = [
            'id' => $img_ids,
        ];

        return $this->delImgsByWhere($where);
    }

    /**
     * 根据条件删除图片
     *
     * @param array $where
     * @return bool
     */
    private function delImgsByWhere(array $where)
    {
        //取出全部图片对应的路径，然后删除图片记录，然后删除图片文件
        $imgs_data = $this->getImgListDiskUrl($where, 200);
        if ($imgs_data['total'] == 0 || empty($imgs_data['data'])) {
            //无记录可删
            return true;
        }

        $urls = array_column($imgs_data['data'], 'img_url');

        $res = $this->imgModel->delImgs($where);
        if ($res === false) {
            Log::record('删除图片记录失败：' . $this->imgModel->getLastSql());
            return false;
        }

        if ($res > $imgs_data['total']) {
            Log::record('删除图片行数异常：' . $this->imgModel->getLastSql());
            return false;
        }

        //删除磁盘对应文件
        $this->delImgFromDisk($urls);

        return true;
    }

    /**
     * 根据图片所属者的信息作为条件删除图片数据
     *
     * @author mayy
     * @date 2017-8-15
     * @param $table_name
     * @param $table_id
     * @param $img_type
     * @return bool
     */
    public function deleteImgsByData($table_name, $table_id, $img_type)
    {
        if (empty($table_name) || empty($table_id) || !in_array($img_type, $this->imgType)) {
            Log::record('删除图片请求参数错误：' . implode(',', func_get_args()));
            exception('缺少删除图片的必要参数！');
        }

        $where = [
            'table_name'=> $table_name,
            'table_id'  => is_array($table_id) ? $table_id : [$table_id],
            'img_type'  => $img_type,
        ];

        return $this->delImgsByWhere($where);
    }

    /**
     * 获取图片列表，返回的url为http可访问的地址
     *
     * @param $where
     * @param $limit
     * @param $fields
     */
    public function getImgListHttpUrl($where, $limit = 20, $fields = true)
    {
        if ($fields!== true && strpos($fields, 'img_url') === false) {
            $fields = true;
        }

        $imgs_data = $this->imgModel->getList($where, $limit, false, $fields);
        if (!empty($imgs_data['data'])) {
            foreach ($imgs_data['data'] as &$v) {
                $v['img_url'] = !empty(['img_url']) ? get_img_http_url($v['img_url']) : '';
            }
        }

        return $imgs_data;
    }

    /**
     * 获取图片列表，返回的url为http可访问的地址
     *
     * @param $where
     * @param $limit
     */
    public function getImgListDiskUrl($where, $limit = 20)
    {
        $imgs_data = $this->imgModel->getList($where, $limit);
        if (!empty($imgs_data['data'])) {
            foreach ($imgs_data['data'] as &$v) {
                $v['img_url'] = !empty($v['img_url']) ? IMG_PATH . $v['img_url'] : '';
            }
        }

        return $imgs_data;
    }

}